//
//  DATManager.m
//  MapEdit
//
//  Created by Steven Canfield on 29/06/07.
//  Copyright 2007 __MyCompanyName__. All rights reserved.
//

#import "DATManager.h"


@implementation DATManager

static NSString * unitPath = @"arr\\units.dat";
static NSString * flingyPath = @"arr\\flingy.dat";
static NSString * spritePath = @"arr\\sprites.dat";
static NSString * imagePath = @"arr\\images.dat";
static NSString * imageStringsPath = @"arr\\images.tbl";

#pragma mark Initialization
static DATManager * sharedManager = nil;
+ (DATManager*)sharedManager
{
    @synchronized(self) {
        if (sharedManager == nil) {
            [[self alloc] init]; // assignment not done here
			
			NSError * err = NULL;
			
			NSString * broodDataPath = [NSString stringWithFormat:@"%@/%@", [DATManager starcraftFilesDirectory], @"Brood War Data"];
			MPQArchive * broodArchive = [MPQArchive archiveWithPath:broodDataPath error:&err];
			
			NSString * regularDataPath = [NSString stringWithFormat:@"%@/%@", [DATManager starcraftFilesDirectory], @"StarCraft Data"];
			MPQArchive *regularArchive = [MPQArchive archiveWithPath:regularDataPath error:&err];
			NSLog( [[regularArchive archiveInfo] description]);
			
			if( broodArchive == NULL || regularArchive == NULL ) {
				/* Couldn't Load Archive */
				NSLog( [err description] );
			}
			
			DATUnit		* units		= [[DATUnit alloc] initWithData:[broodArchive copyDataForFile:unitPath error:&err]];
			DATFlingy	* flingy	= [[DATFlingy alloc] initWithData:[broodArchive copyDataForFile:flingyPath error:&err]];
			DATSprite	* sprite	= [[DATSprite alloc] initWithData:[broodArchive copyDataForFile:spritePath error:&err]];
			DATImage	* image		= [[DATImage alloc] initWithData:[broodArchive copyDataForFile:imagePath error:&err]];
			TBLFile		* tbl		= [[TBLFile alloc] initWithData:[broodArchive copyDataForFile:imageStringsPath error:&err]];
			
			[sharedManager setUnits:units];
			[sharedManager setFlingy:flingy];
			[sharedManager setSprites:sprite];
			[sharedManager setImages:image];
			[sharedManager setImagesTBL:tbl];
			[sharedManager setBroodArchive:broodArchive];
			[sharedManager setRegularArchive:regularArchive];
			
			[units release];
			[flingy release];
			[sprite release];
			[image release];
			[tbl release];
			
			if( err != NULL ) {
				NSLog( [err description]);
			}
			
			NSData * cpData =  [[NSData alloc] initWithData:[regularArchive copyDataForFile:@"tileset\\jungle.wpe"]];
			NSData * ppData = [[NSData alloc] initWithData:[regularArchive copyDataForFile:@"game\\tunit.pcx"]];
			[cpData writeToFile:@"/Users/scanfield/Desktop/cpData.dat" options:NSAtomicWrite error:NULL];
			[ppData writeToFile:@"/Users/scanfield/Desktop/ppData.dat" options:NSAtomicWrite error:NULL];
        }
    }
    return sharedManager;
}

+ (NSString *)starcraftFilesDirectory {
	NSString * pathToStarcraft = [[NSWorkspace sharedWorkspace] fullPathForApplication:@"Starcraft (Carbon)"];
	return [pathToStarcraft stringByDeletingLastPathComponent];
}

#pragma mark Images

- (NSString *)spritePathForUnitIdentifier:(int)index {
	dat_unit_t * unit = [_units unitAtIndex:index];
	dat_flingy_t * flingy = [_flingy flingyAtIndex: unit->flingy_index ];
	dat_sprite_t * sprite = [_sprites spriteAtIndex: flingy->sprite_index];
	dat_image_t	 * image = [_images imageAtIndex: sprite->image_index ];
	NSString * path = [_imagesTBL stringAtIndex: image->image_tbl_index-1];
	return path;
}

- (NSString *)shadowPathForUnitIdentifier:(int)index {
	dat_unit_t * unit = [_units unitAtIndex:index];
	dat_flingy_t * flingy = [_flingy flingyAtIndex: unit->flingy_index ];
	dat_sprite_t * sprite = [_sprites spriteAtIndex: flingy->sprite_index];
	dat_image_t	 * image = [_images imageAtIndex: sprite->image_index ];
	NSString * path = [_imagesTBL stringAtIndex: image->image_tbl_index];
	return path;
}

- (Sprite *)spriteForUnitIdentifier:(int)index {
	NSString * spritePath = [self spritePathForUnitIdentifier:index];
	NSString * path = [NSString stringWithFormat:@"unit\\%@", [spritePath lowercaseString]];
	return [self spriteForPath:path];
}

- (Sprite *)shadowForUnitIdentifier:(int)index {
	NSString * shadowPath = [self shadowPathForUnitIdentifier:index];
	NSString * path = [NSString stringWithFormat:@"unit\\%@", [shadowPath lowercaseString]];
	NSLog(@"Shadow Path: %@", path );
	return [self spriteForPath:path];
}

- (Sprite *)spriteForPath:(NSString *)path {
	if( _spriteCache == NULL ) {
		_spriteCache = [[NSMutableDictionary alloc] init];
	}
	if( _palette == NULL ) {
		_palette = [[ColorPalette alloc] initWithData:[_regularArchive copyDataForFile:@"tileset\\jungle.wpe"]];
		[Sprite setUnitPalette:_palette];
	}

	if( _playerPalette == NULL ) {
		_playerPalette = [[PCXFile alloc] initWithData:[_regularArchive copyDataForFile:@"game\\tunit.pcx"]];
		[Sprite setPlayerPalette:_playerPalette];
	}
	
	
	NSError *err;
	if( [_spriteCache objectForKey:path] == NULL ) {
		NSData * broodData = NULL;
		NSData * regularData = NULL;
		broodData	= [_broodArchive copyDataForFile:path error:&err];
		regularData = [_regularArchive copyDataForFile:path error:&err];
		
		NSData * spriteData;
		if( regularData != NULL && broodData == NULL ) {
			spriteData = regularData;
		} else if( regularData == NULL && broodData != NULL ) {
			spriteData = broodData;
		} else if( regularData != NULL && broodData != NULL ) {
			spriteData = broodData;
		} else if (regularData == NULL && broodData == NULL ) {
		} else {
			NSLog(@"!");
		}
		
		if( err != NULL ) {
			NSLog( [err description] );
		}
		
		NSString *pth = [NSString stringWithFormat:@"/Users/scanfield/Desktop/sprites/%@", [path lastPathComponent]];
		[spriteData writeToFile:pth options:NSAtomicWrite error:NULL];

		Sprite * sprite = [[Sprite alloc] initWithData:spriteData];// palette:_palette playerPalette:_playerPalette];
		[_spriteCache setObject:sprite forKey:path];
	}
	return [_spriteCache objectForKey:path];
}

#pragma mark Accessors

- (void)setUnits:(DATUnit *)units {
	if( units != _units ) {
		[_units release];
		_units = [units retain];
	}
}

- (void)setFlingy:(DATFlingy *)flingy {
	if( flingy != _flingy ) {
		[_flingy release];
		_flingy = [flingy retain];
	}
}

- (void)setSprites:(DATSprite *)sprites {
	if( sprites != _sprites ) {
		[_sprites release];
		_sprites = [sprites retain];
	}
}

- (void)setImages:(DATImage *)images {
	if( images != _images ) {
		[_images release];
		_images = [images retain];
	}
}

- (void)setImagesTBL:(TBLFile *)imagesTBL {
	if( imagesTBL != _imagesTBL ) {
		[_imagesTBL release];
		_imagesTBL = [imagesTBL retain];
	}
}

- (void)setBroodArchive:(MPQArchive *)archive {
	if( archive != _broodArchive ) {
		[_broodArchive release];
		_broodArchive = [archive retain];
	}
}

- (void)setRegularArchive:(MPQArchive *)archive {
	if( archive != _regularArchive ) {
		[_regularArchive release];
		_regularArchive = [archive retain];
	}
}

#pragma mark Singleton Housekeeping
/* Singleton Housekeeping */
+ (id)allocWithZone:(NSZone *)zone
{
    @synchronized(self) {
        if (sharedManager == nil) {
            sharedManager = [super allocWithZone:zone];
            return sharedManager;  // assignment and return on first allocation
        }
    }
    return nil; //on subsequent allocation attempts return nil
}
 
- (id)copyWithZone:(NSZone *)zone
{
    return self;
}
 
- (id)retain
{
    return self;
}
 
- (unsigned)retainCount
{
    return UINT_MAX;  //denotes an object that cannot be released
}
 
- (void)release
{
}
 
- (id)autorelease
{
    return self;
}

@end
